﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Data;
using System.IO;
using System.Linq;
using Cinch;
using System.Windows.Threading;
using System.Configuration;


namespace Anata.Client
{
    /// <summary>
    /// </summary>
    public class PromoSelectViewModel : ViewModelBase
    {
        #region Data
        #region Data.Primitives
        private int? idLayanan;

        private String filterKeyword = "";

        private bool isAllLoaded = false;
        private int pageLoaded = 0;
        private DispatcherTimer filterTimer;
        #endregion

        #region Data.Rules
        #endregion

        #region Data.VMs
        private DispatcherNotifiedObservableCollection<PromoThumbnailViewModel> promos;
        private ICollectionView promosCV;
        #endregion

        #region Data.Services
        private IViewAwareStatus viewAwareStatusService;
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion


        #region Constructor
        [ImportingConstructor]
        public PromoSelectViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            //this.viewAwareStatusService = viewAwareStatusService;
            this.referenceProvider = referenceProvider;
            //this.viewAwareStatusService.ViewLoaded += ViewAwareStatusService_ViewLoaded;
            #endregion

            #region Constructor.SetupCommands
            //KonsumenNewCommand = new SimpleCommand<Object, Object>(CanExecuteKonsumenNewCommand, ExecuteKonsumenNewCommand);
            //KonsumenRefreshCommand = new SimpleCommand<Object, Object>(CanExecuteKonsumenRefreshCommand, ExecuteKonsumenRefreshCommand);
            FilterKeyUpCommand = new SimpleCommand<Object, Object>(CanExecuteFilterKeyUpCommand, ExecuteFilterKeyUpCommand);
            ListMouseLeftButtonUpCommand = new SimpleCommand<Object, Object>(CanExecuteListMouseLeftButtonUpCommand, ExecuteListMouseLeftButtonUpCommand);
            #endregion

            #region Constructor.SetupDataWrappers
            #endregion

            #region Constructor.SetupValidationRules
            #endregion

            #region Constructor.SetupVMs
            Promos = new DispatcherNotifiedObservableCollection<PromoThumbnailViewModel>();
            DataCV = CollectionViewSource.GetDefaultView(promos);
            #endregion

            Mediator.Instance.Register(this);

            #region Constructor.Filter
            filterTimer = new DispatcherTimer();
            filterTimer.Interval = TimeSpan.FromMilliseconds(
                Int32.Parse(ConfigurationManager.AppSettings["FilterResponsiveness"].ToString()));
            filterTimer.Tick += new EventHandler(LazyFilterCallback);
            #endregion

        }
        #endregion

        #region Public Properties
        #region Public.Commands
        public SimpleCommand<Object, Object> FilterKeyUpCommand { get; private set; }
        public SimpleCommand<Object, Object> ListMouseLeftButtonUpCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs filterKeywordChangeArgs =
            ObservableHelper.CreateArgs<PromoSelectViewModel>(x => x.FilterKeyword);
        public String FilterKeyword
        {
            get { return filterKeyword; }
            set
            {
                filterKeyword = value;
                NotifyPropertyChanged(filterKeywordChangeArgs);
                LazyFilter();
            }
        }
        #endregion

        #region Public.CachedCollection
        #endregion

        #region Public.DataVMs
        /// <summary>
        /// Loaded Konsumen
        /// </summary>
        static PropertyChangedEventArgs promosChangeArgs =
            ObservableHelper.CreateArgs<PromoSelectViewModel>(x => x.Promos);

        public DispatcherNotifiedObservableCollection<PromoThumbnailViewModel> Promos
        {
            get { return promos; }
            set
            {
                promos = value;
                NotifyPropertyChanged(promosChangeArgs);
            }
        }
        /// <summary>
        /// Loaded Konsumen
        /// </summary>
        static PropertyChangedEventArgs promosCVChangeArgs =
            ObservableHelper.CreateArgs<PromoSelectViewModel>(x => x.DataCV);

        public ICollectionView DataCV
        {
            get { return promosCV; }
            set
            {
                promosCV = value;
                NotifyPropertyChanged(promosCVChangeArgs);
            }
        }
        #endregion
        #endregion

        #region Command Handlers
        /// <summary>
        /// </summary>
        private bool CanExecuteFilterKeyUpCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteFilterKeyUpCommand(Object args)
        {
            LazyFilter();
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteListMouseLeftButtonUpCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteListMouseLeftButtonUpCommand(Object args)
        {
            if (promosCV.CurrentPosition > -1)
            {
                CloseActivePopUpCommand.Execute(true);
            }
        }
        #endregion

        #region IViewStatusAwareInjectionAware Members
        #endregion

        #region Private Methods
        #region PrivateMethods.ViewLoaded
        private void ViewAwareStatusService_ViewLoaded()
        {
            LoadPromos();
        }
        #endregion

        #region PrivateMethods.Filter
        private void LazyFilter()
        {
            filterTimer.Stop();
            filterTimer.Start();
            Console.WriteLine("typing");
        }
        private void LazyFilterCallback(object sender, EventArgs e)
        {
            Console.WriteLine("stopped typing, filtering with keyword: " + filterKeyword);
            filterTimer.Stop();
            if (filterKeyword != "")
            {
                promosCV.Filter = new Predicate<object>(LazyFilterPredicate);
            }
            else
            {
                promosCV.Filter = null;
            }
        }
        private bool LazyFilterPredicate(object row)
        {
            PromoThumbnailViewModel ptvm = row as PromoThumbnailViewModel;
            return (ptvm.Nama.ToLower().Contains(filterKeyword.ToLower()));
        }
        #endregion

        #region PrivateMethods.Loader
        /// <summary>
        /// loader
        /// </summary>
        private void LoadPromos()
        {
            referenceProvider.LazyFetchPromos(pageLoaded, PostLoadPromos);
        }

        /// <summary>
        /// post loader
        /// </summary>
        private void PostLoadPromos(List<PromoThumbnailViewModel> ptvms)
        {
            //rekursif sampai semua diload
            int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
            foreach (var ptvm in ptvms)
            {
                if (IsValidPromo(ptvm))
                {
                    promos.Add(ptvm);
                }
            }

            if (ptvms.Count != pageSize)
            {
                //basis
                //sudah habis, done loading
                isAllLoaded = true;
            }
            else
            {
                //rekurens
                ++pageLoaded;
                LoadPromos();
            }
        }
        #endregion

        #region PrivateMethods.ValidityChecker
        private bool IsValidPromo(PromoThumbnailViewModel ptvm)
        {
            return !ptvm.IdLayanan.HasValue || IsTimeValidPromo(ptvm);
        }

        private bool IsTimeValidPromo(PromoThumbnailViewModel ptvm)
        {
            bool retval = false;
            if (ptvm.IdLayanan == idLayanan)
            {
                DateTime now = DateTime.Now;
                DateTime start = ptvm.WaktuMulai.Value;
                DateTime end = ptvm.WaktuSelesai.Value;
                if (!ptvm.IsOnce)
                {
                    TimeSpan span = end - start;
                    if (ptvm.IsDaily)
                    {
                        start = new DateTime(now.Year, now.Month, now.Day, start.Hour, start.Minute, start.Second);
                        if (now < start)
                        {
                            start = start.AddDays(-1);
                        }
                    }
                    else if (ptvm.IsWeekly)
                    {
                        if (now.DayOfWeek < start.DayOfWeek)
                        {
                            start = now.AddDays(-7 + start.DayOfWeek - now.DayOfWeek);
                        }
                        else 
                        {
                            start = now.AddDays(start.DayOfWeek - now.DayOfWeek);
                        }
                    }
                    else if (ptvm.IsMonthly)
                    {
                        start = new DateTime(now.Year, now.Month, start.Day, start.Hour, start.Minute, start.Second);
                        if (now < start)
                        {
                            start = start.AddMonths(-1);
                        }
                    }
                    else if (ptvm.IsYearly)
                    {
                        start = new DateTime(now.Year, start.Month, start.Day, start.Hour, start.Minute, start.Second);
                        if (now < start)
                        {
                            start = start.AddYears(-1);
                        }
                    }
                    end = start + span;
                }
                retval = now >= start && now <= end;
            }
            return retval;
        }
        #endregion
        #endregion

        #region PublicMethods
        public void SetCriteria(int? idLayanan)
        {
            this.idLayanan = idLayanan;
            LoadPromos();
        }
        #endregion
    }

}